#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>

#include "exiterror.h"


/*/////////////////////// Constantes de exiterror - BEGIN - /////////////////////////////*/
/*///////////////////////////////////////////////////////////////////////////////////////*/

#define ERROR_STR_SUCCESS				"Process completed."
#define ERROR_STR_INVALID_OPTION			"Invalid option."
#define ERROR_STR_MISSING_REQUIRED_PARAMETER		"Missing required parameter."
#define ERROR_STR_INVALID_COMMAND_LINE			"Invalid command line."

#define ERROR_STR_NEED_ARGUMENTS			"Invalid option arguments."
#define ERROR_STR_NOT_NEED_ARGUMENTS			"Missing option arguments."

#define ERROR_STR_ONLY_ONE_OUTPUT			"Option output is duplicated."
#define ERROR_STR_ONLY_ONE_RESOLUTION			"Option resolution is duplicated."


#define ERROR_STR_INVALID_RESOLUTION			"Invalid resolution."

#define ERROR_STR_ALLOCATING_MEMORY                 	"Cannot allocate memory."


#define ERROR_STR_CANNOT_OPEN_FILE			"Cannot open file: \"%s\"."

#define ERROR_STR_CANNOT_OPEN_FILE_AUX			"Cannot open file."
#define ERROR_STR_WRITING_TO_OUTPUT			"Cannot write to output."
#define ERROR_STR_PROCESSING_INPUT			"Unexpected error processing input."
#define ERROR_STR_UNEXPECTED				"Unexpected error."

#define ERROR_STR_FATAL_DESC				"Fatal error (code %d): %s\n"
#define ERROR_STR_SUCCESS_DESC				"Success (code %d): %s\n"

/*///////////////////////// Constantes de exiterror - END - /////////////////////////////*/
/*///////////////////////////////////////////////////////////////////////////////////////*/


/*/////////////////// Variables globales que se exportan - BEGIN - //////////////////////*/
/*///////////////////////////////////////////////////////////////////////////////////////*/

/*
Puntero al nombre del archivo que está siendo procesado
para ser usado en caso de error en el mensaje al usuario.
*/
const char* pprocfilename = NULL;

/*/////////////////// Variables globales que se exportan - END - ////////////////////////*/
/*///////////////////////////////////////////////////////////////////////////////////////*/



/*
Convierte un código de error pasado por parámetro en un mensaje de texto
descriptivo y lo imprime por stderr.

1er parámetro: Código de error.


devuelve: -
*/
void messageerror(const int status)
{

    char* pcmessage;
    char* pcauxmsg = NULL;

    switch (status)
    {
    case ERROR_SUCCESS:
        pcmessage = ERROR_STR_SUCCESS;
        break;
    case ERROR_INVALID_OPTION:
        pcmessage = ERROR_STR_INVALID_OPTION;
        break;
    case ERROR_MISSING_REQUIRED_PARAMETER:
        pcmessage = ERROR_STR_MISSING_REQUIRED_PARAMETER;
        break;
    case ERROR_INVALID_COMMAND_LINE:
        pcmessage = ERROR_STR_INVALID_COMMAND_LINE;
        break;
    case ERROR_INVALID_RESOLUTION:
        pcmessage = ERROR_STR_INVALID_RESOLUTION;
        break;
    case ERROR_ONLY_ONE_OUTPUT:
        pcmessage = ERROR_STR_ONLY_ONE_OUTPUT;
        break;
    case ERROR_ONLY_ONE_RESOLUTION:
        pcmessage = ERROR_STR_ONLY_ONE_RESOLUTION;
        break;
    case ERROR_NEED_ARGUMENTS:
        pcmessage = ERROR_STR_NEED_ARGUMENTS;
        break;
    case ERROR_NOT_NEED_ARGUMENTS:
        pcmessage = ERROR_STR_NOT_NEED_ARGUMENTS;
        break;
    case ERROR_ALLOCATING_MEMORY:
        pcmessage = ERROR_STR_ALLOCATING_MEMORY;
        break;
    case ERROR_CANNOT_OPEN_FILE:
    case ERROR_CANNOT_OPEN_OUTPUT_FILE:

        pcauxmsg = (char*) malloc(strlen(ERROR_STR_CANNOT_OPEN_FILE) +
                                  strlen(pprocfilename) + 1);

        if (pcauxmsg)
        {
            sprintf(pcauxmsg, ERROR_STR_CANNOT_OPEN_FILE, pprocfilename);
            pcmessage = pcauxmsg;
        }
        else
            pcmessage = ERROR_STR_CANNOT_OPEN_FILE_AUX;

        break;
    case ERROR_WRITING_TO_OUTPUT:
        pcmessage = ERROR_STR_WRITING_TO_OUTPUT;
        break;
    case ERROR_PROCESSING_INPUT:
        pcmessage = ERROR_STR_PROCESSING_INPUT;
        break;
    default:
        pcmessage = ERROR_STR_UNEXPECTED;
    }


    fprintf(stderr, status ? ERROR_STR_FATAL_DESC : ERROR_STR_SUCCESS_DESC, status, pcmessage);

    if (pcauxmsg)
        free(pcauxmsg);
}


/*
Imprime por stderr un mensaje.

1er parámetro: Mensaje con formato.
n-avo parámetro: Parámetros de formato.

devuelve: -
*/
void messageinfo(const char * format, ...)
{
    va_list ap;
    va_start(ap, format);
    vfprintf(stderr, format, ap);
    va_end(ap);
}
